﻿using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using WPF_UI_Lightningchart.Events;
using WPF_UI_Lightningchart.Models;
using WPF_UI_Lightningchart.Services;
using WPF_UI_Lightningchart.UserControls;
using WPF_UI_Lightningchart.ViewModels;

namespace WPF_UI_Lightningchart.Views
{
    /// <summary>
    /// GridLayoutUserControl.xaml 的交互逻辑
    /// </summary>
    public partial class GridLayoutUserControl : UserControl
    {
        private readonly IEventAggregator _eventAggregator;
        private readonly LayoutManager _layoutManager;
        public GridLayoutUserControl(IEventAggregator eventAggregator)
        {
            InitializeComponent();
            _eventAggregator = eventAggregator;
            _layoutManager = new LayoutManager();
        }

        // =================== 拖动元素 相关方法 ===================

        private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var listBox = sender as ListBox;
            var item = FindAncestor<ListBoxItem>((DependencyObject)e.OriginalSource);
            if (item != null)
            {
                var data = item.DataContext as SensorViewModel;
                DragDrop.DoDragDrop(listBox, data, DragDropEffects.Move);
            }
        }
        private static T FindAncestor<T>(DependencyObject current) where T : DependencyObject
        {
            while (current != null)
            {
                if (current is T)
                {
                    return (T)current;
                }
                current = VisualTreeHelper.GetParent(current);
            }
            return null;
        }
        public void SensorList_DragOver(object sender, DragEventArgs e)
        {
            e.Effects = e.Data.GetDataPresent(typeof(SensorViewModel)) ? DragDropEffects.Move : DragDropEffects.None;
            e.Handled = true;
        }


        // =================== 区域布局 相关方法 ===================
        private void LayoutComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (LayoutComboBox.SelectedItem is ComboBoxItem selectedItem)
            {
                SetLayoutType(selectedItem.Content.ToString());
            }
        }

        private void SetLayoutType(string type)
        {
            switch (type)
            {
                case "垂直两格":
                    SetGridLayout(MainGrid, true, 1, 1);
                    break;
                case "水平两格":
                    SetGridLayout(MainGrid, false, 1, 1);
                    break;
                case "垂直三格：上 2 下 1":
                    SetGridLayout(MainGrid, true, 2, 1);
                    break;
                case "水平三格：左 2 右 1":
                    SetGridLayout(MainGrid, false, 2, 1);
                    break;
                case "垂直四格：上 2 下 2":
                    SetGridLayout(MainGrid, true, 2, 2);
                    break;
                case "垂直五格：上 3 下 2":
                    SetGridLayout(MainGrid, true, 3, 2);
                    break;
                case "水平五格：左 3 右 2":
                    SetGridLayout(MainGrid, false, 3, 2);
                    break;
                case "水平六格：上 3 下 3":
                    SetGridLayout(MainGrid, false, 3, 3);
                    break;
                    // 添加其他布局选项
            }
        }
        private void ClearMainGrid(Grid mainGrid)
        {
            foreach (var child in MainGrid.Children.OfType<Border>())
            {
                if (child.Child is IDisposable oldControl) oldControl.Dispose();
                child.Child = null;
            }
            mainGrid.Children.Clear();
            mainGrid.RowDefinitions.Clear();
            mainGrid.ColumnDefinitions.Clear();
        }
        public void SetGridLayout(Grid mainGrid, bool isVertical, int topSections, int bottomSections)
        {
            ClearMainGrid(mainGrid);
            mainGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
            mainGrid.VerticalAlignment = VerticalAlignment.Stretch;

            if (isVertical)
            {
                mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
                mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(5, GridUnitType.Auto) });
                mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            }
            else
            {
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5, GridUnitType.Auto) });
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            }

            var topGrid = new Grid() { Name = "topGrid", HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch };
            for (int i = 0; i < topSections; i++)
            {
                if (isVertical)
                {
                    topGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                    if (i < topSections - 1)
                        topGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5, GridUnitType.Pixel) });
                }
                else
                {
                    topGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
                    if (i < topSections - 1)
                        topGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(5, GridUnitType.Pixel) });
                }

                CreateRegion(topGrid, $"region{i + 1}", isVertical ? 0 : i * 2, isVertical ? i * 2 : 0);
            }

            for (int i = 1; i < topSections * 2 - 1; i += 2)
            {
                AddGridSplitter(topGrid, isVertical ? 0 : i, isVertical ? i : 0, isVertical ? GridResizeDirection.Columns : GridResizeDirection.Rows);
            }

            if (isVertical)
                Grid.SetRow(topGrid, 0);
            else
                Grid.SetColumn(topGrid, 0);

            mainGrid.Children.Add(topGrid);

            var bottomGrid = new Grid() { Name = "bottomGrid", HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch };
            for (int i = 0; i < bottomSections; i++)
            {
                if (isVertical)
                {
                    bottomGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                    if (i < bottomSections - 1)
                        bottomGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5, GridUnitType.Pixel) });
                }
                else
                {
                    bottomGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
                    if (i < bottomSections - 1)
                        bottomGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(5, GridUnitType.Pixel) });
                }

                CreateRegion(bottomGrid, $"region{topSections + i + 1}", isVertical ? 0 : i * 2, isVertical ? i * 2 : 0);
            }

            for (int i = 1; i < bottomSections * 2 - 1; i += 2)
            {
                AddGridSplitter(bottomGrid, isVertical ? 0 : i, isVertical ? i : 0, isVertical ? GridResizeDirection.Columns : GridResizeDirection.Rows);
            }

            if (isVertical)
                Grid.SetRow(bottomGrid, 2);
            else
                Grid.SetColumn(bottomGrid, 2);

            mainGrid.Children.Add(bottomGrid);

            AddGridSplitter(mainGrid, isVertical ? 1 : 0, isVertical ? 0 : 1, isVertical ? GridResizeDirection.Rows : GridResizeDirection.Columns);

        }
        private void CreateRegion(Grid parentGrid, string name, int row, int column)
        {
            Border card = new Border
            {
                BorderBrush = Brushes.Transparent,
                BorderThickness = new Thickness(0),
                Background = Brushes.White,
                CornerRadius = new CornerRadius(5),
                Margin = new Thickness(2),
                Padding = new Thickness(5),
                AllowDrop = true,
                Effect = new DropShadowEffect
                {
                    Color = Colors.Gray,
                    BlurRadius = 8,
                    ShadowDepth = 1,
                    Opacity = 0.3
                }
            };

            card.Name = name;
            card.MouseRightButtonDown += (sender, e) => Region_MouseRightButtonDown(sender, e);
            TextBlock textBlock = new TextBlock
            {
                Text = "Please choose the control!",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                FontSize = 16,
                FontWeight = FontWeights.Bold,
                Margin = new Thickness(0),
                Background = Brushes.Transparent
            };
            card.Child = textBlock;
            Grid.SetRow(card, row);
            Grid.SetColumn(card, column);
            parentGrid.Children.Add(card);
        }
        private void AddGridSplitter(Grid parentGrid, int row, int column, GridResizeDirection direction)
        {
            GridSplitter splitter = new GridSplitter { Opacity = 0, ResizeDirection = direction, HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Width = direction == GridResizeDirection.Columns ? 5 : double.NaN, Height = direction == GridResizeDirection.Rows ? 5 : double.NaN, MaxWidth = MainGrid.ActualWidth, MaxHeight = MainGrid.ActualWidth, };

            string splitterName = direction == GridResizeDirection.Rows
                ? $"{parentGrid.Name}_Splitter_Row_{row}"
                : $"{parentGrid.Name}_Splitter_Column_{column}";
            splitter.Name = splitterName;

            Grid.SetRow(splitter, row);
            Grid.SetColumn(splitter, column);

            splitter.MouseEnter += (sender, e) => { splitter.Opacity = 0.6; };
            splitter.MouseLeave += (sender, e) => { splitter.Opacity = 0; };

            parentGrid.Children.Add(splitter);
        }

        private IEnumerable<Border> GetAllBorders(DependencyObject parent)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);

                if (child is Border border)
                {
                    yield return border;
                }
                foreach (var subChild in GetAllBorders(child))
                {
                    yield return subChild;
                }
            }
        }


        // =================== 布局保存 相关方法 ===================

        private void SaveLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            SaveCurrentLayout(" ", LayoutComboBox.Text);
        }
        private void LoadLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            LoadLayout($"Layout_{_layoutManager.GetSavedLayouts().Count}");
        }
        public void CreateNewLayout()
        {
            SaveLayoutButton.Visibility = Visibility.Visible;
            LayoutComboBox.Visibility = Visibility.Visible;
            ClearMainGrid(MainGrid);
        }
        public void SaveCurrentLayout(string layoutName, string layoutType)
        {
            var layoutData = new LayoutData
            {
                LayoutType = layoutType
            };

            SaveRegionPositions(MainGrid, layoutData);

            var name = $"Layout_{_layoutManager.GetSavedLayouts().Count + 1}";

            _layoutManager.SaveLayout(name, layoutData);
            _eventAggregator.GetEvent<LayoutEvent>().Publish();
        }
        private void SaveRegionPositions(Grid grid, LayoutData layoutData)
        {
            foreach (var child in grid.Children)
            {
                if (child is Border border)
                {
                    if (border.Name.Contains("region"))
                    {
                        double position = (grid.RowDefinitions.Count > grid.ColumnDefinitions.Count) ?
                            border.ActualHeight / (grid.ActualHeight - ((grid.RowDefinitions.Count+1)/2-1) * 5) : border.ActualWidth / (grid.ActualWidth - ((grid.ColumnDefinitions.Count + 1) / 2 - 1) * 5);
                        layoutData.RegionPositions.Add(border.Name, position);
                    }

                    layoutData.RegionContentMap[border.Name] = border.Child?.GetType().Name ?? "Unknown";
                }
                else if (child is Grid nestedGrid)
                {
                    if (nestedGrid.Name.Contains("Grid"))
                    {
                        double position = (grid.RowDefinitions.Count > grid.ColumnDefinitions.Count) ?
                            nestedGrid.ActualHeight / (grid.ActualHeight - ((grid.RowDefinitions.Count + 1) / 2 - 1) * 5) : nestedGrid.ActualWidth / (grid.ActualWidth - ((grid.ColumnDefinitions.Count + 1) / 2 - 1) * 5);
                        layoutData.RegionPositions.Add(nestedGrid.Name,position);
                    }

                    var nestedLayoutData = new LayoutData
                    {
                        LayoutType = "Nested Layout Type"
                    };
                    SaveRegionPositions(nestedGrid, nestedLayoutData);
                    layoutData.NestedLayouts.Add(nestedLayoutData);
                }
            }
        }

        public async void LoadLayout(string layoutName)
        {
            var layoutData = await Task.Run(() => _layoutManager.LoadLayout(layoutName));

            if (layoutData == null)
            {
                MessageBox.Show("布局不存在或加载失败！");
                return;
            }

            Dispatcher.Invoke(() =>
            {
                SaveLayoutButton.Visibility = Visibility.Collapsed;
                LayoutComboBox.Visibility = Visibility.Collapsed;
                ClearMainGrid(MainGrid);

                // 设置主Grid的布局类型
                SetLayoutType(layoutData.LayoutType);
                // 恢复分隔条位置
                RestoreRegionPositions(MainGrid, layoutData);
            });
        }
        private void RestoreRegionPositions(Grid grid, LayoutData layoutData)
        {
            grid.UpdateLayout();
            double totalWidth = grid.ActualWidth;
            double totalHeight = grid.ActualHeight;

            if (totalWidth == 0 || totalHeight == 0)
            {
                return; // 提前返回，避免宽高为 0 时的错误
            }

            int nestedIndex = 0;

            foreach (var child in grid.Children)
            {
                if (child is Border border && layoutData.RegionPositions.ContainsKey(border.Name))
                {
                    double position = layoutData.RegionPositions[border.Name];
                    int row = Grid.GetRow(border);
                    int column = Grid.GetColumn(border);

                    if (grid.RowDefinitions.Count > grid.ColumnDefinitions.Count && row < grid.RowDefinitions.Count)
                    {
                        // 设置所在行的高度比例
                        grid.RowDefinitions[row].Height = new GridLength(position, GridUnitType.Star);
                    }
                    else if (column < grid.ColumnDefinitions.Count)
                    {
                        grid.ColumnDefinitions[column].Width = new GridLength(position, GridUnitType.Star);
                    }

                    // 更新 Border 内容
                    string contentType = layoutData.RegionContentMap.ContainsKey(border.Name) ? layoutData.RegionContentMap[border.Name] : "Unknown";
                    UpdateRegionContent(border, contentType);
                }
                else if (child is Grid nestedGrid && nestedIndex < layoutData.NestedLayouts.Count)
                {
                    if (layoutData.RegionPositions.ContainsKey(nestedGrid.Name))
                    {
                        double position = layoutData.RegionPositions[nestedGrid.Name];
                        int row = Grid.GetRow(nestedGrid);
                        int column = Grid.GetColumn(nestedGrid);

                        if (grid.RowDefinitions.Count > grid.ColumnDefinitions.Count && row < grid.RowDefinitions.Count)
                        {
                            grid.RowDefinitions[row].Height = new GridLength(position, GridUnitType.Star);
                        }
                        else if (column < grid.ColumnDefinitions.Count)
                        {
                            grid.ColumnDefinitions[column].Width = new GridLength(position, GridUnitType.Star);
                        }
                    }
                    RestoreRegionPositions(nestedGrid, layoutData.NestedLayouts[nestedIndex]);
                    nestedIndex++;
                }
            }
        }

        private void Region_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Border selectedRegion = sender as Border;
            ContextMenu contextMenu = CreateContextMenu(selectedRegion);
            selectedRegion.ContextMenu = contextMenu;
            contextMenu.IsOpen = true;
        }

        private ContextMenu CreateContextMenu(Border region)
        {
            ContextMenu contextMenu = new ContextMenu();
            contextMenu.Width = 200;
            MenuItem nyquistPlotItem = new MenuItem { Header = "奈氏图" };
            nyquistPlotItem.Click += (s, args) => UpdateRegionContent(region, "NyquistBindableControl");
            MenuItem bodeBindableItem = new MenuItem { Header = "波特图" };
            bodeBindableItem.Click += (s, args) => UpdateRegionContent(region, "BodeBindableControl");
            MenuItem spectrum3DItem = new MenuItem { Header = "FFT瀑布图" };
            spectrum3DItem.Click += (s, args) => UpdateRegionContent(region, "Spectrum3DControl");
            MenuItem spectrum2DItem = new MenuItem { Header = "FFT光谱图" };
            spectrum2DItem.Click += (s, args) => UpdateRegionContent(region, "Spectrum2DControl");
            MenuItem areaSpectrumItem = new MenuItem { Header = "FFT频谱图" };
            areaSpectrumItem.Click += (s, args) => UpdateRegionContent(region, "AreaSpectrumControl");
            MenuItem noneItem = new MenuItem { Header = "空白" };
            noneItem.Click += (s, args) => UpdateRegionContent(region, "None");
            contextMenu.Items.Add(nyquistPlotItem);
            contextMenu.Items.Add(bodeBindableItem);
            contextMenu.Items.Add(spectrum3DItem);
            contextMenu.Items.Add(spectrum2DItem);
            contextMenu.Items.Add(areaSpectrumItem);
            contextMenu.Items.Add(noneItem);
            return contextMenu;
        }

        private void UpdateRegionContent(Border region, string contentType)
        {
            Dispatcher.Invoke(() =>
            {
                if (region.Child is IDisposable oldControl) oldControl.Dispose();

                region.Child = null;

                switch (contentType)
                {
                    case "BodeBindableControl":
                        region.Child = new BodeBindableControl(_eventAggregator);
                        break;
                    case "NyquistBindableControl":
                        region.Child = new NyquistBindableControl(_eventAggregator);
                        break;
                    case "Spectrum3DControl":
                        region.Child = new Spectrum3DControl(_eventAggregator);
                        break;
                    case "Spectrum2DControl":
                        region.Child = new Spectrum2DControl(_eventAggregator);
                        break;
                    case "AreaSpectrumControl":
                        region.Child = new AreaSpectrumControl(_eventAggregator);
                        break;
                    case "None":
                        region.Child = null;
                        break;
                }
            });
        }


    }
}
